#ifndef __ONEWAYROAD__
#define __ONEWAYROAD__

#include <dispatch_system/definitions.h>
#include <dispatch_system/vehicle.h>
#include <vector>
#include <mutex>

namespace moying
{
namespace navigation
{

class OneWayRoad;
using OneWayRoadPtr = std::shared_ptr<OneWayRoad>;


class VehicleInfo{
    
public:
    VehicleInfo(){};
    VehicleInfo(VehiclePtr v){
        vehicle = v;
        exit_time = 0;
    };

    bool operator < (const VehicleInfo& vi)const{
        return  vehicle < vi.vehicle;
    };

public:
    VehiclePtr vehicle;
    time_t exit_time;
};

//单向道类,
/***********NOTICE:如果机器人在窄道里下线，窄道不会移除机器人，再次上线前，窄道被锁定 (后面修改成,机器人下线后,只锁定一段时间)
 * 机器人在进入单行道时会参考当前单行道的朝向,路径方向需与单行道朝向一致才可通行,否则重新规划路径
*/
class OneWayRoad{


public:

    OneWayRoad();

    bool set_available_orientation(std::vector<Orientation> orients);
    bool set_cur_orientation(Orientation orient);
    Orientation cur_orientation(){return cur_orientation_;}
    bool set_temp_fix_orientation(Orientation orient){temp_fix_orientation_ = orient;}
    Orientation temp_fix_orientation(){return temp_fix_orientation_;}
    void handleVehiclePoseUpdate(VehiclePtr vehicle,MapCell cell);
    void addCell(MapCell cell);
    void mergeOneWayRoad(OneWayRoadPtr other_road,bool clear_other_road=true);
    bool isVehicleInRoad(VehiclePtr vehicle);
    bool isVehicleInRoad(VehiclePtr vehicle,VehicleInfo& vi);
    bool isCellInRoad(MapCell cell);
    bool isAvailabeOrientation(Orientation orient);
    int  roadLength();
    void printfInfo();
    void printRobots();
    int minx(){return minx_;}
    int maxx(){return maxx_;}
    int miny(){return miny_;}
    int maxy(){return maxy_;}
    int orientation_count(){return available_orientation_.size();}
    void increaseRefuseEnterTimes();
    bool canEnterRoad(Orientation orientation,VehiclePtr vehicle=nullptr);
    int getVehicleCountInRoad(){return vehicles_in_road_.size();}
    unsigned int id(){return id_;}
    void getAllVehicles(std::vector<unsigned int>& vehicle_ids);

    bool addVehicle(VehiclePtr vehicle);
    bool removeVehicle(VehiclePtr vehicle);
    int getCloseTheta(int th);

private:

    std::recursive_mutex        vehicle_mutex_;         //同步机器人容器
    std::vector<Orientation>    available_orientation_; //可通行的方向
    Orientation                 cur_orientation_;       //当前的通行方向,当机器人即将进入单行道时才考虑这个方向
    Orientation                 temp_fix_orientation_;  //临时固定的通行方向,如果不是未定义,路径规划时就要考虑这个值
    std::set<VehicleInfo>        vehicles_in_road_;      //通道中的机器人集合
    int                         max_vehicle_count_;     //通道中允许同时存在的机器人数量
    unsigned int                id_;                    //单向道id标识
    std::vector<MapCell>        cells_in_road_;         //单向道中的cell
    int minx_;  //通道中cell最小x值
    int maxx_;  //通道中cell最大x值
    int miny_;  //通道中cell最小y值
    int maxy_;  //通道中cell最大y值
    int refuse_enter_times_=0;   //拒绝进入的次数,当拒绝进入的次数到达上限时,设置临时固定方向.机器人全部离开后,该值清零.

};


}
}

#endif